package net.oschina.bilbodai.common.beanutil.bean;

import net.oschina.bilbodai.common.beanutil.bean.type.NullType;

import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Map;

/**
 * 属性的拷贝类型
 * code说明:
 * 低6位,每种类型占一位, 如:
 * <pre>
 *     1                 2               3                  4               5               6
 *     Simple      Collection        Array              Map                -               -
 * </pre>
 * 第7位为类型位,每种类型占一个值
 *
 * @author daimao  Date: 16/5/27 Time: 下午7:37
 * @version $Id$
 */
public enum PropertyDumpType {

    /**
     * 未设置
     */
    NONE(0x0, NullType.class, NullType.class),

    /**
     * 最简单的方式: FooTarget.setName(Foo.getName())
     */
    REFERENCE(0x1, NullType.class, NullType.class),

    /**
     * 源或者目标字段是单个可以拷贝的对象,调用{@link IBeanAccessor#propertyDump(Object, Object)} 把源字段值,目标字段值放入
     */
    SINGLE(0x2, NullType.class, NullType.class),

    /**
     * 当源或目标为集合类型是,需要把源的元素遍历加载目标中
     */
    IT_LIST(0x3, Collection.class, LinkedList.class),

    /**
     * 当源或目标为集合类型是,需要把源的元素遍历加载目标中
     */
    IT_SET(0x4, Collection.class, LinkedHashSet.class),

    /**
     * 遍历迭代,对于源和目标类型中一个字段为List类型
     * 则需要把源字段中每一个元素依次取出并且生成和调用{@link IBeanAccessor#propertyDump(Object, Object)}
     * 加入目标字段中。则使用这个类型
     */
    LIST(0x5, Collection.class, LinkedList.class),

    /**
     * 遍历迭代,对于源和目标类型中一个字段为Set类型
     * 则需要把源字段中每一个元素依次取出并且生成和调用{@link IBeanAccessor#propertyDump(Object, Object)}
     * 加入目标字段中。则使用这个类型
     */
    SET(0x6, Collection.class, LinkedHashSet.class),

    /**
     * 遍历迭代,对于源和目标类型中一个字段为数组
     * 则需要把源字段中每一个元素依次取出并且生成和调用{@link IBeanAccessor#propertyDump(Object, Object)}
     * 加入目标字段中。则使用这个类型
     */
    ARRAY(0x7, NullType.class, NullType.class),

    /**
     * 遍历迭代,对于源和目标类型中一个字段为Map类型
     * 则需要把源字段中每一个Entry元素依次取出KEY,VALUE直接加入目标字段中。则使用这个类型
     */
    IT_MAP(0x8, Map.class, LinkedHashMap.class),

    /**
     * 遍历迭代,对于源和目标类型中一个字段为Map类型
     * 则需要把源字段中每一个Entry元素依次取出KEY,VALUE并且生成和调用{@link IBeanAccessor#propertyDump(Object, Object)}
     * 加入目标字段中。则使用这个类型
     */
    MAP(0x9, Map.class, LinkedHashMap.class),

    /**
     * 枚举类型，一般适用枚举转String的场景
     */
    ENUM(0x10, NullType.class, NullType.class),

    /**
     * 字符串类型，一般适用枚举转String的场景
     */
    STRING(0x11, NullType.class, NullType.class),

    /**
     * 原始类型，一般用于引用到原始类型或者相反
     */
    PRIME(0x12, NullType.class, NullType.class);

//    private static final long TYPE_MASK = 0x0_111111;

    private final long code;
    /**
     * 接口类型,如果有
     */
    private final Class<?> type;
    /**
     * 默认的接口类型实现,如果有
     */
    private final Class<?> typeImpl;

    PropertyDumpType(long code, Class<?> type, Class<?> typeImpl) {
        this.code = code;
        this.type = type;
        this.typeImpl = typeImpl;
    }

    public long getCode() {
        return code;
    }

    public Class<?> getTypeImpl() {
        return typeImpl;
    }

    public Class<?> getType() {
        return type;
    }

    public boolean isNotSet() {
        return NONE == this;
    }

    public boolean isSet() {
        return NONE != this;
    }
}